const vm = new Vue({
  el:'#app',
  data: {
    name: 'zf',
    age: 12
  }
})



// 可以通过实例的$options 来获取去创造实例上传递的参数
vm.$options 
// vue中会判断如果是$开头的属性不会被变成响应式数据


// initData  实现 data computed method props 
// 属性劫持
// walk 遍历对象 定义响应式


// 实现这步
vm.name
vm._data
// 去vm上面取值就去 vm._data


// 递归对象
let v = {
  data: {
    name: 'zf',
    age: {
     a: 1 
    }
  }
}

// 赋值一个对象
vm.name = {a: 1}

// 如果是个数组的话  会对数组的每个下标进行观测  这个要做下处理  因为平时操作数组很少用 下标来操作  arr[1] = 2  浪费性能
// 方法劫持  变异方法
// 重写数组方法

let oldArrMethod = Array.prototype
let arrPrototype = Object.create(oldArrMethod)
let methods = [
  'push',
  'pop'
]

methods.forEach(item => {
  arrPrototype[item] = function() {
    oldArrMethod[item].call(this, ...args)
  }
})

// 数组原先是对象的处理  以及后面加的做操作
let obj = {
  arr: [{a:1}]
}
vm.arr.push({a:1})
// push splice unshift 三个方法做新增拦截
//  观测方法 然后问题  这个观测的方法 不在一个地方  
// this是Observe 对象实例  既可以判断是否已经被观测过
data.__obj__ = this  //因为递归 死循环   改写
Object.defineProperty(data, '__ob__', {
  value: this,
  enumerable: false
})


// 先判断有没有render  在判断有没有template有的话给他编译成render函数  没有的话 就取outHtml   渲染插入页面
Vue.prototype.$mount

// compileToFunction(template)
// 返回一个虚拟节点
// diff  虚拟节点比较 


// 模板变成字符串
// {/* <div id="app">{{msg}}</div> */}
// _c('div', {
//   attrs: {id: app}
// },[_v(_s(msg))])
// 讲 template转成ast语法树
// ast描述语法的


// 构建 ast 语法树
// 不停解析字符串 直到他没了
// parseHTML
// 假如以 <  开头   解析开始标签 {tag: 'div', attrs: [{name: 'xx}]}
// 1. 删除 <div 
// 2. 删除  属性 attr  
// 3. 直到 >
// 4. 解析文本 第0个开始 截取到 第二个< 开始
// 5. 匹配到结束标签 删除
// 把内容变成一颗语法树
// 构建父子关系
// 返回 root


// ast语法树  转成render函数
// genCode 字符串拼接成 我想要的 _c('div', )
// 包装成函数  with(this) {return ${code}}
// new Function(with(this) {return ${code}})

// 增加原型方法 _render  _update _c _s之类的
// 渲染 mountComponent
// _render方法  调用生成的render函数  生成vnode
// update(vnode) ->
// patch(el, vnode)  



// 创建Watcher  收集依赖
new Watcher(vm, updateComponent, ()=>{
  // ...
}, true)
// 让属性记住对应的渲染函数   如果属性发生变化就调用对应的渲染函数
// 模板取值 就会触发get
// 我们给每个属性增加一个收集器 通过收集器来收集watcher
// 一个属性有dep -> watcher

// new Dep()
// 全局的 target 指向当前 watcher
// 数组收集watcher 
// 数组嵌套情况 依赖收集 


// observe实例下面的dep属性就是给整个对象

// 更新去重
// 队列收集 
// nexTick


// diff 算法平级比对
// 1. 对比标签名  key 是否一致
// 2. 更新属性
// 3. 比较下级
// 4. 一方有一方没   两方都有
//    两方都有 diff 算法
//          头尾 两个指针  两边四个指针
//               结束条件 只要有一方 头超过尾
//             头头   尾尾  尾头  头尾   
//             乱序对比  创建一个map  看看有没有能复用的  可以的复用的插入到oldindex前面
//                结束的时候 旧的还没结束  删除     新的还没结束新增
//                   
// vue.mixin  合并到$options  类似于生命周期有自己的合并策略

// watch api 
// 用户的watcher  
// exprOrFn 是一个key 或者 updatecomponent函数
// 用户的get是直接取值


// computed 计算属性 缓存watcher  定义值  dirty来控制缓存
// 依赖收集  两层
// 求完值之后 还有Dep target 
// 计算属性watcher 找到里面依赖的属性  让依赖的属性记录渲染watcher


// 问题
// vue对象新增属性时的收集依赖
// watch 收集依赖的过程
// computed 收集依赖过程


